#pragma once 

/* 会话表的ODB映射操作 */

#include "chat_session_member.hxx"
#include "chat_session_member-odb.hxx"

namespace ChatSystem
{
    //会话成员表ODB操作
    class ChatSessionMemberTable
    {
    public:
        using ptr = std::shared_ptr<ChatSessionMemberTable>;
        ChatSessionMemberTable(const std::shared_ptr<odb::core::database>& db)
        :_db(db)
        {}
        ~ChatSessionMemberTable()
        {}

        // 单个会话成员的新增---向指定会话中添加单个成员
        /*为了便于扩展不止写为void append(const std::string& session_id, const std::string& uid)，这样虽然简化了使用这个接口的操作，
        但是一旦ChatSessionMember表中的成员发生变化了就append这个接口就无法适用了，需要我们修改这个接口；为了方便扩展，在使用append这个
        接口的时候构造好ChatSessionMember对象传进来，这样即使ChatSessionMember的成员发生变化也不许要修改append这个接口 */
        bool append(ChatSessionMember& chat_session_member)
        {
            //数据的所有操作都会有可能导致程序的崩溃，所以需要捕捉异常防止程序的退出；
            try
            {
                //获取对象开启事务
                odb::transaction trans(_db->begin());
                _db->persist(chat_session_member);
                //提交事务
                trans.commit();
            }
            catch(const std::exception& e)
            {
                LOG_ERROR("在 {} 会话中新增单个成员 {} 时失败, {}!", chat_session_member.chat_session_id(), 
                    chat_session_member.user_id(), e.what());
                return false;
            }
            return true;   
        }

        // 多个会话成员的新增---向指定会话中添加多个成员
        bool append(const std::vector<ChatSessionMember>& chat_session_member_lists)
        {
            //数据的所有操作都会有可能导致程序的崩溃，所以需要捕捉异常防止程序的退出；
            try
            {
                //获取对象开启事务
                odb::transaction trans(_db->begin());
                for(auto chat_session_member : chat_session_member_lists)
                {
                    _db->persist(chat_session_member);
                }
                //提交事务
                trans.commit();
            }
            catch(const std::exception& e)
            {
                LOG_ERROR("在会话 {} 中新增 {} 个成员时失败, {}!", chat_session_member_lists[0].chat_session_id(), 
                chat_session_member_lists.size(), e.what());
                return false;
            }
            return true;  
        }

        // 删除会话的单个成员---从指定会话中删除单个成员。odb框架的删除，需要将要删除的对象查询出来再删除
        bool remove(const ChatSessionMember& chat_session_member)
        {
            //数据的所有操作都会有可能导致程序的崩溃，所以需要捕捉异常防止程序的退出；
            try
            {
                //获取对象开启事务
                odb::transaction trans(_db->begin());
                //1. 先查询
                typedef odb::query<ChatSessionMember> query;
                typedef odb::result<ChatSessionMember> result;
                _db->erase_query<ChatSessionMember>(query::chat_session_id == chat_session_member.chat_session_id()
                    && query::user_id == chat_session_member.user_id());
                //提交事务
                trans.commit();
            }
            catch(const std::exception& e)
            {
                LOG_ERROR("删除 {} 会话中的 {} 成员失败, {}!", chat_session_member.chat_session_id(), chat_session_member.user_id(), e.what());
                return false;
            }
            return true;  
        }

        // 删除会话的所有成员---在删除会话的时候使用
        bool remove(const std::string& chat_session_id)
        {
            //数据的所有操作都会有可能导致程序的崩溃，所以需要捕捉异常防止程序的退出；
            try
            {
                //获取对象开启事务
                odb::transaction trans(_db->begin());
                //1. 先查询
                typedef odb::query<ChatSessionMember> query;
                typedef odb::result<ChatSessionMember> result;
                _db->erase_query<ChatSessionMember>(query::chat_session_id == chat_session_id);
                //提交事务
                trans.commit();
            }
            catch(const std::exception& e)
            {
                LOG_ERROR("删除 {} 会话的所有成员失败, {}!", chat_session_id, e.what());
                return false;
            }
            return true;  
        }

        // 获取会话的所有成员---通过会话 ID，获取会话的所有成员 ID
        std::vector<std::string> members(const std::string& chat_session_id)
        {
            std::vector<std::string> res;
            //数据的所有操作都会有可能导致程序的崩溃，所以需要捕捉异常防止程序的退出；
            try
            {
                //3. 获取事务操作对象，开启事务
                odb::transaction trans(_db->begin());
                //4. 数据操作
                typedef odb::query<ChatSessionMember> query;
                typedef odb::result<ChatSessionMember> result;
                result r(_db->query<ChatSessionMember>(query::chat_session_id == chat_session_id));
                for(auto it = r.begin(); it != r.end(); ++it)
                {
                    res.push_back(it->user_id());
                }
                //5. 提交事务
                trans.commit();
            }
            catch(std::exception& e)
            {
                LOG_ERROR("获取会话 {} 中的所有成员时失败, {}", chat_session_id, e.what());
            }
            return res;
        }

    private:
        std::shared_ptr<odb::core::database> _db;   //对数据库的操作都是通过db来操作的---数据库操作句柄
    };
}